<?php

namespace services\buss;

use api\modules\common\services\UploadService;
use api\modules\v1\forms\buss\ContentForm;
use common\components\Service;
use common\helpers\CommonHelper;
use common\helpers\DateHelper;
use common\helpers\RedisHelper;
use common\models\base\CommonStatus;
use common\models\base\Tags;
use common\models\buss\Content;
use common\models\buss\ContentPublishRecord;
use common\models\buss\Doctors;
use common\models\sys\SysFile;
use services\base\CommonRelationService;
use services\base\CommonStatusService;
use services\base\TagsService;
use services\log\LogMemberOpService;
use services\member\MemberService;
use services\sys\SysFileService;
use Yii;
use yii\db\Expression;

/**
 * Class ContentService
 * @package services\buss
 */
class ContentService extends Service
{
    /**
     * 内容列表
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0): array
    {
        $query = Content::find()->alias('c')
            ->select([
                'c.*',
                new Expression('SUM(IF(cpr.read_num IS NULL, 0, read_num)) read_num'),
                new Expression('SUM(IF(cpr.like_num IS NULL, 0, like_num) + IF(cpr.collect_num IS NULL, 0, collect_num) + IF(cpr.comment_num IS NULL, 0, comment_num)) hd_num'),
                'COUNT(cpr.id) publish_num'
            ])
            ->leftJoin(ContentPublishRecord::tableName().' cpr', 'cpr.content_id = c.id and cpr.status = ' . ContentPublishRecord::STATUS_ENABLE)
            ->where([
                'c.project_id' => array_column(MemberService::getAllProjectListCondition(), 'value'),
                'c.status' => Content::STATUS_ENABLE,
            ])
            ->groupBy('c.id');

        if (isset($params['created_stime']) && $params['created_stime']) {
            $query->andWhere(['>=', 'c.created_at', strtotime($params['created_stime'])]);
        }
        if (isset($params['created_etime']) && $params['created_etime']) {
            $query->andWhere(['<=', 'c.created_at', strtotime($params['created_etime'].' 23:59:59')]);
        }
        if (isset($params['keywords']) && $params['keywords']) {
            $query->andWhere([
                'or',
                ['like', 'c.title', $params['keywords']],
                new Expression("JSON_CONTAINS(c.keyword->'$', JSON_ARRAY('{$params['keywords']}'), '$')"),
            ]);
        }
        if (isset($params['project_id']) && $params['project_id']) {
            $query->andWhere(['c.project_id' => $params['project_id']]);
        } else {
            $query->andWhere(['c.project_id' => array_column(MemberService::getProjectListCondition(), 'value')]);
        }
        if (isset($params['tag_ids']) && $params['tag_ids']) {
            $params['tag_ids'] = is_array($params['tag_ids']) ? $params['tag_ids'] : explode(',', $params['tag_ids']);
            $query->andWhere(['c.id' => CommonRelationService::getTagContentIds($params['tag_ids'])]);
        }
        if (isset($params['type']) && $params['type']) {
            $query->andWhere(['c.type' => $params['type']]);
        }
        if (isset($params['created_member_id']) && $params['created_member_id']) {
            $query->andWhere(['c.created_member_id' => $params['created_member_id']]);
        }
        if (isset($params['c_id']) && $params['c_id']) {
            $query->andWhere(['c.c_id' => $params['c_id']]);
        }
        if (isset($params['publish_status']) && is_numeric($params['publish_status'])) {
            $query->andWhere(['c.publish_status' => $params['publish_status']]);
        }
        if (isset($params['doctor_id']) && $params['doctor_id']) {
            $query->andWhere(['c.doctor_id' => $params['doctor_id']]);
        }
        // 排序
        $order = [];
        if (isset($params['order_column']) && $params['order_column']) {
            $sort = isset($params['order_sort']) && $params['order_sort'] == 'asc' ? SORT_ASC : SORT_DESC;
            switch ($params['order_column']) {
                case 'read_num':
                case 'hd_num':
                case 'publish_num':
                    $order["{$params['order_column']}"] = $sort;
                    break;
                default :
                    break;
            }
            $order && $order['c.id'] = SORT_DESC;
        }
        empty($order) && $order = ['c.status' => SORT_DESC, 'c.id' => SORT_DESC];
        return $this->getListPageRes($query, $page, $pageSize, $order);
    }

    /**
     * 格式化列表
     * @param array $data
     * @return array
     */
    public function getListPageFormat(array $data = []): array
    {
        /**
         * @var Doctors[] $doctorList
         */
        $doctorList = Doctors::find()->where(['id' => array_column($data, 'doctor_id')])->indexBy('id')->all();

        $list = [];
//        $contentPublishRecordList = ContentPublishRecordService::statisticNumData(array_column($data, 'id'));
        foreach ($data as $row) {
            $tags = TagsService::getNormalListByIds(Tags::TYPE_CONTENT, CommonRelationService::getContentTagIds($row['id']));
            $doctor = $doctorList[$row['doctor_id']] ?? null;
            $list[] = [
                'id' => $row['id'],
                'title' => $row['title'],
                'project_name' => RedisHelper::getProject($row['project_id'])->project_name ?? '',
                'type_str' => Content::$types[$row['type']] ?? '',
                'tag_arr' => array_column($tags, 'name'),
                'c_name' => RedisHelper::getCommonStatus($row['c_id'])->name ?? '',
                'keyword' => json_decode($row['keyword'], true),
                'publish_status_str' => Content::$publishStatuss[$row['publish_status']] ?? '',
                'is_stream_str' => Content::$isStreams[$row['is_stream']] ?? '',
                'created_member_name' => RedisHelper::getMember($row['created_member_id'])->realname ?? '',
                'created_at_str' => DateHelper::timestampToDate($row['created_at'], DateHelper::DATE_FORMAT_1),
                'change_date' => DateHelper::timestampToDate(strtotime($row['change_date']), DateHelper::DATE_FORMAT_1),
//                'read_num' => $contentPublishRecordList[$row['id']]['read_num'] ?? 0,// 浏览量
//                'hd_num' => $contentPublishRecordList[$row['id']]['like_num'] ?? 0 + $contentPublishRecordList[$row['id']]['collect_num'] ?? 0 + $contentPublishRecordList[$row['id']]['comment_num'] ?? 0,// 互动数：当前文章所有平台的 （“点赞”+“收藏”+“评论”）总和
//                'publish_num' => $contentPublishRecordList[$row['id']]['publish_num'] ?? 0,// 发布次数
                'read_num' => $row['read_num'],
                'hd_num' => $row['hd_num'],
                'publish_num' => $row['publish_num'],
                'doctor_name' => $doctor && $doctor->status != Doctors::STATUS_DELETE ? $doctor->name : '',
            ];
        }
        return $list;
    }

    /**
     * 获取内容创建人IDs
     * @return array
     */
    public static function getCreateMemberIds(): array
    {
        return Content::find()
            ->select(['created_member_id'])
            ->andWhere(['status' => Content::STATUS_ENABLE])
            ->column();
    }

    /**
     * 状态下拉筛选项
     * @return array[]
     */
    public static function getPublishStatusCondition(): array
    {
        return [
            ['value' => Content::PUBLISH_STATUS_ON, 'label' => Content::$publishStatuss[Content::PUBLISH_STATUS_ON]],
            ['value' => Content::PUBLISH_STATUS_OFF, 'label' => Content::$publishStatuss[Content::PUBLISH_STATUS_OFF]],
        ];
    }

    /**
     * 类型下拉筛选项
     * @return array[]
     */
    public static function getTypeCondition(): array
    {
        $types = Content::$types;
        $data = [];
        foreach ($types as $key => $val) {
            $data[] = [
                'value' => $key,
                'label' => $val,
            ];
        }
        return $data;
    }

    /**
     * 操作人列表
     * @return array
     */
    public static function getCreatedMemberList(): array
    {
        $ids = self::getCreateMemberIds();
        return $ids ? MemberService::getListCondition($ids) : [];
    }

    /**
     * 列表筛选项
     * @return array
     */
    public function getSelectCondition(): array
    {
        return [
            'publist_status' => self::getPublishStatusCondition(),
            'type' => self::getTypeCondition(),
            'created_member' => self::getCreatedMemberList(),
            'tag' => TagsService::getListCondition(Tags::TYPE_CONTENT),
            'project' => MemberService::getProjectListCondition(),
            'classify' => CommonStatusService::getListCondition(CommonStatus::TYPE_CONTENT),
            'doctor' => DoctorsService::getListCondition(),
        ];
    }

    /**
     * 内容详情
     * @param array $params
     * @return array
     */
    public function getInfo(int $id): array
    {
        $data = [];
        // 内容信息
        $content = Content::findOne($id);
        if ($content) {
            $attachment = [];
            foreach ($content->attachment as $file) {
                $attachment[] = [
                    'file' => $file,
                    'file_url' => UploadService::getFileTrueUrl(SysFile::SITE_CONTENT, SysFile::MODULE_CONTENT, $file),
                ];
            }
            $data = [
                'id' => $content->id,
                'project_id' => $content->project_id,
                'type' => $content->type,
                'title' => $content->title,
                'content' => $content->content,
                'keyword' => $content->keyword,
                'c_id' => $content->c_id,
                'is_stream' => $content->is_stream,
                'publish_status' => $content->publish_status,
                'attachment' => $attachment,
                'tag_ids' => array_column(TagsService::getNormalListByIds(Tags::TYPE_CONTENT, CommonRelationService::getContentTagIds($content->id)), 'id'),
                'doctor_id' => $content->doctor_id,
            ];
        }
        $condition = [
            'publist_status' => self::getPublishStatusCondition(),
            'type' => self::getTypeCondition(),
            'tag' => TagsService::getEditCondition(Tags::TYPE_CONTENT,$data['tag_ids'] ?? null),
            'classify' => CommonStatusService::getEditCondition(CommonStatus::TYPE_CONTENT, $data['c_id'] ?? null),
            'project' => MemberService::getProjectEditCondition($data['project_id'] ?? null),
            'doctor' => DoctorsService::getEditCondition($data['doctor_id'] ?? null),
        ];
        if ($content) {
            $data['tag_ids'] = array_intersect($data['tag_ids'], array_column($condition['tag'], 'value'));
            if (in_array($data['project_id'], array_column($condition['project'], 'value')) === false) {
                $data['project_id'] = 0;
            }
            if (in_array($data['c_id'], array_column($condition['classify'], 'value')) === false) {
                $data['c_id'] = 0;
            }
            if (in_array($data['doctor_id'], array_column($condition['doctor'], 'value')) === false) {
                $data['doctor_id'] = 0;
            }
        }
        return array_merge($data, [
            'support_img' => UploadService::$imageTypeArr,
            'support_video' => UploadService::$videoTypeArr,
        ], ['condition' => $condition]);
    }

    /**
     * 下载内容详情
     * @param array $params
     * @return array
     */
    public function getDownloadInfo(int $id): array
    {
        // 内容信息
        $content = Content::findOne($id);
        if (empty($content)) {
            return CommonHelper::api(422, '内容不存在');
        }

        $attachment = [];
        foreach ($content->attachment as $file) {
            $attachment[] = [
                'file' => $file,
                'file_url' => UploadService::getFileTrueUrl(SysFile::SITE_CONTENT, SysFile::MODULE_CONTENT, $file),
            ];
        }
        return [
            'id' => $content->id,
            'type' => $content->type,
            'title' => $content->title,
            'content' => $content->content,
            'attachment' => $attachment,
        ];
    }

    /**
     * 发布详情
     * @return array
     */
    public function getPublishInfo(): array
    {
        return [
            'doctor' => DoctorsService::getEditCondition(),
        ];
    }

    /**
     * 编辑内容
     * @param Content $content
     * @param ContentForm $model
     * @return Content
     * @throws \Exception
     */
    public static function editModel(Content $content, ContentForm $model): Content
    {
        $content->project_id = $model->project_id;
        $content->type = $model->type;
        $content->title = $model->title ?: '';
        $content->doctor_id = $model->getDoctor()->id ?? 0;
        $content->c_id = $model->c_id;
        $content->keyword = $model->keyword ?: [];
        $content->publish_status = $model->publish_status;
        $content->is_stream = $model->is_stream;
        $content->attachment = $model->attachment;
        $content->content = $model->content ?: '';
        if ($model->getScenario() == 'create') {
            $content->created_member_id = Yii::$app->user->identity->member_id;
            $content->change_date = DateHelper::timestampToDate(time());
            $content->operation_id = Yii::$app->user->identity->member_id;
            $content->operation_name = Yii::$app->user->identity->member->realname;
            $content->status = Content::STATUS_ENABLE;
        }
        $content->saveAndCheckResult();

        return $content;
    }

    /**
     * 新增内容
     * @param array $params
     * @return array
     */
    public function create(array $params): array
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            $model = new ContentForm();
            $model->setScenario('create');
            $model->attributes = $params;
            if (!$model->validate()) {
                $transaction->rollBack();
                // 返回数据验证失败
                return CommonHelper::api(422, $this->getError($model));
            }

            // 1-1.新增内容
            $content = new Content();
            $content = self::editModel($content, $model);
            // 1-2.新增标签
            CommonRelationService::editModel(Tags::TYPE_CONTENT, $content->id, $model->getAddTagIds());
            // 2.更新文件信息
            SysFileService::editFile(SysFile::SITE_CONTENT, SysFile::MODULE_CONTENT, $model->getAddAttachment());
            // 3.日志
            LogMemberOpService::createContentLog($model, $content);

            $transaction->commit();
            return ['id' => $content->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 编辑内容
     * @param array $params
     * @return array
     */
    public function edit(array $params): array
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            $model = new ContentForm();
            $model->setScenario('edit');
            $model->attributes = $params;
            if (!$model->validate()) {
                $transaction->rollBack();
                // 返回数据验证失败
                return CommonHelper::api(422, $this->getError($model));
            }

            // 1-1.更新内容
            $oldContent = new Content();
            $oldContent->setAttributes($model->getContent()->getAttributes());
            $content = self::editModel($model->getContent(), $model);
            // 1-2.新增标签
            CommonRelationService::editModel(Tags::TYPE_CONTENT, $content->id, $model->getAddTagIds(), $model->getDelTagIds());
            // 2.更新文件信息
            SysFileService::editFile(SysFile::SITE_CONTENT, SysFile::MODULE_CONTENT, $model->getAddAttachment(), $model->getDelAttachment());
            // 3.日志
            if (LogMemberOpService::createContentLog($model, $content, $oldContent)) {// 存在日志说明表单有更新
                // 4.更新修改日期
                $content->change_date = DateHelper::timestampToDate(time());
                $content->operation_id = Yii::$app->user->identity->member_id;
                $content->operation_name = Yii::$app->user->identity->member->realname;
                $content->saveAndCheckResult();
            }

            $transaction->commit();
            return ['id' => $content->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 删除内容
     * @param ContentForm $model
     * @return array
     */
    public function delete(ContentForm $model): array
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1.更新内容
            $content = $model->getContent();
            $content->status = Content::STATUS_DELETE;
            $content->operation_id = Yii::$app->user->identity->member_id;
            $content->operation_name = Yii::$app->user->identity->member->realname;
            $content->saveAndCheckResult();
            // 2.更新文件信息
            SysFileService::editFile(SysFile::SITE_CONTENT, SysFile::MODULE_CONTENT, '', $content->attachment);
            // 3.日志
            LogMemberOpService::createContentLog($model, $content);

            $transaction->commit();
            return ['id' => $content->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 下载内容
     * @param array $params
     * @return array
     */
    public function download(ContentForm $model): array
    {
        // 内容信息
        $content = $model->getContent();
        if (in_array($content->project_id, array_column($model->getHaveProjectList(), 'value')) === false) {
            return CommonHelper::api(422, '未绑定该项目，无权限下载');
        }

        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1.更新下载次数
            $content->download_num += 1;
            $content->saveAndCheckResult();
            // 2.日志
            LogMemberOpService::createContentLog($model, $content);

            $transaction->commit();

            if ($model->is_zip == 1) {
                // 3.输出文件
                $this->createDownloadZip($content);
            } else {// 返回下载视频地址
                return [
                    'download_url' => UploadService::getFileDownloadUrl(SysFile::SITE_CONTENT, SysFile::MODULE_CONTENT, $content->attachment[0])
                ];
            }

            return ['id' => $content->id];
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 生成下载zip并输出
     * @param Content $content
     * @return void
     */
    private function createDownloadZip(Content $content)
    {
        // 创建临时目录
        $dir = Yii::getAlias('@attachment').'/tmp/content_zip/';
        !is_dir($dir) && mkdir($dir, 0777, true);
        // 生成.txt文件
        $txtPath = $dir."{$content->id}_".CommonHelper::getRandomAuthKey().".txt";
        file_put_contents($txtPath, strip_tags($content->content));
        // 创建zip
        $zipName = "{$content->title}.zip";
        $zipPath = $dir.$zipName;
        $zip = new \ZipArchive();
        $zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
        $zip->addFile($txtPath, "txt/content.txt");// txt加入zip
        if ($content->type == Content::TYPE_IMAGE) {
            foreach ($content->attachment as $index => $file) {
                $filePath = UploadService::getFileTruePath(SysFile::SITE_CONTENT, SysFile::MODULE_CONTENT, $file);
                $no = $index + 1;
                $zip->addFile($filePath, "image/{$no}" . substr($file, strripos($file, '.')));
            }
        }
        $zip->close();
        // 输出文件
        Yii::$app->response->sendFile($zipPath, $zipName);
        // 删除临时文件
        @unlink($txtPath);
        @unlink($zipPath);
    }
}
